#include <iostream>
#include <simulator/memory/segment.h>
#include <simulator/report/report.h>
#include <simulator/bitTools/bitTools.h>


Segment::Segment(u64 index, u64 addrBegin, u64 memSize, const u8 data[], u64 fileSize, bool canRead, bool canWrite,
                 bool canExecute, SegmentKind segmentKind) {
    m_index = index;
    m_addrBegin = addrBegin;
    m_memSize = memSize;

    m_data.resize(memSize, 0);
    for (u64 i = 0; i < fileSize; ++i)
        m_data[i] = data[i];

    R = canRead;
    W = canWrite;
    X = canExecute;
    m_segmentKind = segmentKind;
}

void Segment::write(u64 offset, u64 size, const u8 data[]) {
    if (!W) {
        warningMacro("当前段不允许写入数据!");
        return;
    }

    if (size == 0) {
        return;
    }

    if (offset + (size - 1) < offset || offset + (size - 1) > m_memSize) {
        warningMacro("写入数据溢出，写内存失败!");
        return;
    }

    for (u64 i = offset; i < offset + size; ++i) {
        m_data[i] = data[i - offset];
    }
}

void Segment::write(u64 offset, u64 size, const std::vector<u8> &data) {
    if (!W) {
        warningMacro("当前段不允许写入数据!");
        return;
    }

    if (size == 0) {
        return;
    }

    if (offset + (size - 1) < offset || offset + (size - 1) >= m_memSize) {
        warningMacro("写入数据溢出，写内存失败!");
        return;
    }

    for (u64 i = offset; i < offset + size; ++i) {
        m_data[i] = data[i - offset];
    }
}

std::vector<u8> Segment::readNBytes(u64 offset, u64 N) {
    if (!R) {
        warningMacro("当前段不允许读出数据!");
        return {};
    }

    if (N == 0) {
        return {};
    }

    if (offset + (N - 1) < offset || offset + (N - 1) >= m_memSize) {
        warningMacro("读取数据越界，读取错误!");
        return {};
    }

    std::vector<u8> res;
    for (u64 i = 0; i < N; ++i)
        res.push_back(m_data[offset + i]);
    return std::move(res);
}


bool Segment::canRead() const {
    return R;
}

bool Segment::canWrite() const {
    return W;
}

bool Segment::canExecute() const {
    return X;
}

u64 Segment::getSegmentSize() const {
    return m_memSize;
}

u64 Segment::getAddressBegin() const {
    return m_addrBegin;
}

void Segment::printSegmentInfo() const {
    std::cout << "index:" << m_index << " beginAddress:"
              << dec2hex(m_addrBegin) + " memSize:" + dec2hex(m_memSize) + " R:" << R << " W:"
              << W << " X:" << X << std::endl;
}

Segment::Segment(const Segment &segment) {
    m_index = segment.m_index;
    // 段类型
    m_segmentKind = segment.m_segmentKind;
    // 段的权限，执行
    X = segment.X;
    // 段的权限，写
    W = segment.W;
    // 段的权限，读
    R = segment.R;
    // 段加载到内存中的大小，字节为单位
    m_memSize = segment.m_memSize;
    // 段加载到内存中的起始地址
    m_addrBegin = segment.m_addrBegin;
    // 段中的字节数据
    m_data = segment.m_data;
}
